﻿using System;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml;
using System.Xml.XPath;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;

namespace Chatu.MsBuildTasks
{
    public class ConnStringUpdateTask : Task
    {
        #region Fields

        private const string XPATH = @"//configuration/connectionStrings/add[@name='{0}']/@connectionString";
        private const string REGEX = @"\w+\s?\w+=[\w\.,\d]+";
        private string _xmlFileName;
        private string _name;
        private string _attribute;
        private string _value;

        #endregion

        #region Properties

        [Required]
        public string XmlFileName
        {
            get { return _xmlFileName; }
            set { _xmlFileName = value; }
        }

        [Required]
        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }

        [Required]
        public string Attribute
        {
            get { return _attribute; }
            set { _attribute = value; }
        }

        [Required]
        public string Value
        {
            get { return _value; }
            set { _value = value; }
        }

        #endregion

        #region Methods

        public override bool Execute()
        {
            try
            {
                Log.LogMessage("ConnStringUpdate File: {0}", _xmlFileName);

                XmlDocument document = new XmlDocument();
                document.Load(_xmlFileName);

                XPathNavigator navigator = document.CreateNavigator();
                XmlNamespaceManager nsResolver = new XmlNamespaceManager(navigator.NameTable);
                XPathExpression expr = XPathExpression.Compile(string.Format(XPATH, _name), nsResolver);
                XPathNodeIterator iterator = navigator.Select(expr);

                while (iterator.MoveNext())
                {
                    MatchCollection matches = Regex.Matches(iterator.Current.Value, REGEX);
                    string[] values = new string[matches.Count];

                    for (int i = 0; i < matches.Count; i++)
                    {
                        string[] attributes = matches[i].Value.Split(new char[] { '=' });

                        if (attributes[0] == _attribute)
                            attributes[1] = _value;

                        values[i] = string.Join("=", attributes);
                    }

                    iterator.Current.SetValue(string.Join(";", values));
                }

                using (XmlTextWriter writer = new XmlTextWriter(_xmlFileName, Encoding.UTF8))
                {
                    writer.Formatting = Formatting.Indented;
                    document.Save(writer);
                    writer.Close();
                }
            }
            catch (Exception exception)
            {
                Log.LogErrorFromException(exception);
                return false;
            }

            Log.LogMessage("ConnStringUpdate Result: {0}", _value);
            return true;
        }

        #endregion
    }
}